package com.reger.l2cache.pipeline.ops;

import java.util.List;
import java.util.Map;

import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

public interface RedisGeoPipeline<K, M> extends RedisKeyPipeline<K> {

	@Nullable
	Long geoAdd(K key, Point point, M member);

	@Nullable
	default Long geoAdd(K key, GeoLocation<M> location) {

		Assert.notNull(key, "Key must not be null!");
		Assert.notNull(location, "Location must not be null!");

		return geoAdd(key, location.getPoint(), location.getName());
	}

	@Nullable
	Long geoAdd(K key, Map<M, Point> memberCoordinateMap);

	@Nullable
	Long geoAdd(K key, Iterable<GeoLocation<M>> locations);

	@Nullable
	Distance geoDist(K key, M member1, M member2);

	@Nullable
	Distance geoDist(K key, M member1, M member2, Metric metric);

	@Nullable
	List<String> geoHash(K key, @SuppressWarnings("unchecked") M... members);

	@Nullable
	List<Point> geoPos(K key, @SuppressWarnings("unchecked") M... members);

	@Nullable
	GeoResults<GeoLocation<M>> geoRadius(K key, Circle within);

	@Nullable
	GeoResults<GeoLocation<M>> geoRadius(K key, Circle within, GeoRadiusCommandArgs args);

	@Nullable
	default GeoResults<GeoLocation<M>> geoRadiusByMember(K key, M member, double radius) {
		return geoRadiusByMember(key, member, new Distance(radius, DistanceUnit.METERS));
	}

	@Nullable
	GeoResults<GeoLocation<M>> geoRadiusByMember(K key, M member, Distance radius);

	@Nullable
	GeoResults<GeoLocation<M>> geoRadiusByMember(K key, M member, Distance radius, GeoRadiusCommandArgs args);

	@Nullable
	Long geoRemove(K key, @SuppressWarnings("unchecked") M... members);

	default RedisGeoPipeline<K, M> toGeoPl() {
		return this;
	}
}
